package com.luo.backend.service;

import com.luo.backend.dto.*;
import com.luo.backend.entity.Merchant;
import com.luo.backend.entity.User;
import com.luo.backend.repository.MerchantRepository;
import com.luo.backend.repository.UserRepository;
import com.luo.backend.util.JwtUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Optional;

/**
 * 认证服务类
 */
@Service
public class AuthService {
    
    private static final Logger logger = LoggerFactory.getLogger(AuthService.class);
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private MerchantRepository merchantRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Autowired
    private JwtUtil jwtUtil;
    
    @Autowired
    private EmailVerificationService emailVerificationService;
    
    /**
     * 用户注册
     */
    @Transactional
    public AuthResponse register(RegisterRequest request) {
        logger.info("用户注册请求: {}", request.getUsername());
        
        // 1. 参数预处理：角色默认值
        if (request.getRole() == null || request.getRole().trim().isEmpty()) {
            request.setRole("customer");
        }
        logger.info("注册角色: {}", request.getRole());
        
        // 2. 商家注册必须提供商家信息
        if ("merchant".equals(request.getRole())) {
            if (request.getMerchantInfo() == null) {
                throw new RuntimeException("商家注册必须提供店铺信息");
            }
            // 验证商家信息字段
            validateMerchantInfo(request.getMerchantInfo());
            logger.info("商家信息验证通过 - 店铺名称: {}", request.getMerchantInfo().getName());
        }
        
        // 3. 检查用户名是否已存在
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        // 4. 检查邮箱是否已存在
        if (userRepository.existsByEmail(request.getEmail())) {
            throw new RuntimeException("邮箱已被注册");
        }
        
        // 5. 验证邮箱验证码
        logger.info("验证注册邮箱验证码 - email: {}, code: {}", request.getEmail(), request.getCode());
        com.luo.backend.entity.EmailVerificationCode verificationCode = 
            emailVerificationService.findValidCode(request.getEmail(), request.getCode(), "register");
        
        if (verificationCode == null) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        // 6. 创建新用户
        User user = new User();
        user.setUsername(request.getUsername());
        user.setEmail(request.getEmail());
        user.setPasswordHash(passwordEncoder.encode(request.getPassword()));
        user.setPhone(request.getPhone());
        user.setRealName(request.getRealName());
        user.setRole(request.getRole()); // ⭐ 设置用户角色
        user.setStatus(1); // 1-正常，0-禁用
        
        // 保存用户
        user = userRepository.save(user);
        logger.info("用户创建成功: id={}, role={}", user.getId(), user.getRole());
        
        // 7. 如果是商家，创建商家记录 ⭐
        if ("merchant".equals(user.getRole())) {
            Merchant merchant = createMerchant(user, request.getMerchantInfo());
            logger.info("商家记录创建成功: id={}, name={}", merchant.getId(), merchant.getName());
            
            // 双向关联：用户关联商家
            user.setMerchantId(merchant.getId());
            user = userRepository.save(user);
            logger.info("用户与商家双向关联完成: userId={}, merchantId={}", user.getId(), merchant.getId());
        }
        
        // 8. 标记验证码已使用
        emailVerificationService.markAsUsed(verificationCode);
        logger.info("验证码已标记为已使用 - email: {}", request.getEmail());
        
        // 9. 生成Token
        String token = jwtUtil.generateToken(user.getId(), user.getUsername());
        
        // 10. 构建响应
        UserResponse userResponse = new UserResponse(user);
        logger.info("注册完成 - userId: {}, role: {}, merchantId: {}", 
            user.getId(), user.getRole(), user.getMerchantId());
        
        return new AuthResponse(userResponse, token, 604800L); // 7天过期
    }
    
    /**
     * 用户登录
     */
    public AuthResponse login(LoginRequest request) {
        logger.info("用户登录请求: {}", request.getUsername());
        
        // 查找用户（支持用户名或邮箱登录）
        Optional<User> userOpt = userRepository.findByUsernameOrEmail(
            request.getUsername(), request.getUsername());
        
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        
        // 检查用户是否激活
        if (user.getStatus() != 1) {
            throw new RuntimeException("账户已被禁用");
        }
        
        // 验证密码
        if (!passwordEncoder.matches(request.getPassword(), user.getPasswordHash())) {
            throw new RuntimeException("密码错误");
        }
        
        // 更新最后登录时间
        user.setLastLoginAt(LocalDateTime.now());
        userRepository.save(user);
        
        logger.info("用户登录成功: {}", user.getId());
        
        // 生成Token
        String token = jwtUtil.generateToken(user.getId(), user.getUsername());
        
        // 构建响应
        UserResponse userResponse = new UserResponse(user);
        return new AuthResponse(userResponse, token, 604800L);
    }
    
    /**
     * 根据ID获取用户信息
     */
    public UserResponse getUserById(Long userId) {
        Optional<User> userOpt = userRepository.findById(userId);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        return new UserResponse(userOpt.get());
    }
    
    /**
     * 更新用户信息
     */
    @Transactional
    public UserResponse updateUser(Long userId, UpdateUserRequest request) {
        Optional<User> userOpt = userRepository.findById(userId);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        
        // 验证并更新真实姓名
        if (request.getRealName() != null) {
            if (request.getRealName().length() < 2 || request.getRealName().length() > 20) {
                throw new RuntimeException("真实姓名长度必须在2-20个字符之间");
            }
            user.setRealName(request.getRealName());
        }
        
        // 验证并更新手机号
        if (request.getPhone() != null) {
            if (!request.getPhone().matches("^1[3-9]\\d{9}$")) {
                throw new RuntimeException("手机号格式不正确");
            }
            user.setPhone(request.getPhone());
        }
        
        // 验证并更新性别
        if (request.getGender() != null) {
            if (!"male".equals(request.getGender()) && 
                !"female".equals(request.getGender()) && 
                !"secret".equals(request.getGender())) {
                throw new RuntimeException("性别参数不正确，必须是 male、female 或 secret");
            }
            user.setGender(request.getGender());
        }
        
        // 更新头像
        if (request.getAvatar() != null) {
            user.setAvatar(request.getAvatar());
        }
        
        user = userRepository.save(user);
        logger.info("用户信息更新成功: {}", userId);
        
        return new UserResponse(user);
    }
    
    /**
     * 修改密码（已登录用户）
     */
    @Transactional
    public void changePassword(Long userId, String oldPassword, String newPassword) {
        logger.info("用户修改密码请求 - userId: {}", userId);
        
        // 1. 查找用户
        Optional<User> userOpt = userRepository.findById(userId);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        
        // 2. 验证旧密码
        if (!passwordEncoder.matches(oldPassword, user.getPasswordHash())) {
            throw new RuntimeException("旧密码错误");
        }
        
        // 3. 验证新密码格式
        if (newPassword == null || newPassword.length() < 6 || newPassword.length() > 20) {
            throw new RuntimeException("新密码长度必须在6-20位之间");
        }
        
        // 4. 更新密码
        user.setPasswordHash(passwordEncoder.encode(newPassword));
        userRepository.save(user);
        
        logger.info("用户密码修改成功 - userId: {}", userId);
    }
    
    /**
     * 重置密码（忘记密码）
     */
    @Transactional
    public void resetPassword(String email, String code, String newPassword) {
        logger.info("重置密码请求 - email: {}", email);
        
        // 1. 验证验证码
        com.luo.backend.entity.EmailVerificationCode verificationCode = 
            emailVerificationService.findValidCode(email, code, "reset_password");
        
        if (verificationCode == null) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        // 2. 查找用户
        Optional<User> userOpt = userRepository.findByEmail(email);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("该邮箱未注册");
        }
        
        User user = userOpt.get();
        
        // 3. 验证新密码格式
        if (newPassword == null || newPassword.length() < 6 || newPassword.length() > 20) {
            throw new RuntimeException("新密码长度必须在6-20位之间");
        }
        
        // 4. 更新密码
        user.setPasswordHash(passwordEncoder.encode(newPassword));
        userRepository.save(user);
        
        // 5. 标记验证码已使用
        emailVerificationService.markAsUsed(verificationCode);
        
        logger.info("密码重置成功 - email: {}", email);
    }
    
    /**
     * 修改邮箱
     */
    @Transactional
    public UserResponse changeEmail(Long userId, String newEmail, String code, String password) {
        logger.info("修改邮箱请求 - userId: {}, newEmail: {}", userId, newEmail);
        
        // 1. 查找当前用户
        Optional<User> userOpt = userRepository.findById(userId);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        
        // 2. 验证登录密码
        if (!passwordEncoder.matches(password, user.getPasswordHash())) {
            throw new RuntimeException("密码错误");
        }
        
        // 3. 验证新邮箱的验证码
        com.luo.backend.entity.EmailVerificationCode verificationCode = 
            emailVerificationService.findValidCode(newEmail, code, "change_email");
        
        if (verificationCode == null) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        // 4. 检查新邮箱是否已被占用
        if (userRepository.existsByEmail(newEmail)) {
            throw new RuntimeException("该邮箱已被其他用户使用");
        }
        
        // 5. 更新邮箱
        user.setEmail(newEmail);
        user = userRepository.save(user);
        
        // 6. 标记验证码已使用
        emailVerificationService.markAsUsed(verificationCode);
        
        logger.info("邮箱修改成功 - userId: {}, newEmail: {}", userId, newEmail);
        
        return new UserResponse(user);
    }
    
    /**
     * 创建商家记录
     */
    private Merchant createMerchant(User user, MerchantInfoRequest merchantInfo) {
        Merchant merchant = new Merchant();
        
        // 关联用户ID
        merchant.setOwnerUserId(user.getId());
        
        // 商家基本信息
        merchant.setName(merchantInfo.getName());
        merchant.setAddress(merchantInfo.getAddress());
        merchant.setPhone(merchantInfo.getPhone());
        merchant.setDescription(merchantInfo.getDescription());
        
        // 设置默认值
        merchant.setStatus(1); // 1-营业中
        merchant.setRating(new BigDecimal("5.00")); // 默认5.00分
        merchant.setRatingCount(0); // 初始评价数为0
        merchant.setMinOrderAmount(new BigDecimal("20.00")); // 默认起送价20元
        merchant.setDeliveryFee(new BigDecimal("3.00")); // 默认配送费3元
        
        // 保存并返回
        return merchantRepository.save(merchant);
    }
    
    /**
     * 验证商家信息
     */
    private void validateMerchantInfo(MerchantInfoRequest merchantInfo) {
        if (merchantInfo.getName() == null || merchantInfo.getName().trim().isEmpty()) {
            throw new RuntimeException("店铺名称不能为空");
        }
        
        if (merchantInfo.getName().length() < 2 || merchantInfo.getName().length() > 100) {
            throw new RuntimeException("店铺名称长度必须在2-100个字符之间");
        }
        
        if (merchantInfo.getAddress() == null || merchantInfo.getAddress().trim().isEmpty()) {
            throw new RuntimeException("店铺地址不能为空");
        }
        
        if (merchantInfo.getAddress().length() < 5 || merchantInfo.getAddress().length() > 200) {
            throw new RuntimeException("店铺地址长度必须在5-200个字符之间");
        }
        
        if (merchantInfo.getPhone() == null || merchantInfo.getPhone().trim().isEmpty()) {
            throw new RuntimeException("店铺电话不能为空");
        }
        
        // 验证电话格式（支持手机号和座机号）
        String phone = merchantInfo.getPhone().trim();
        boolean isValidMobile = phone.matches("^1[3-9]\\d{9}$"); // 手机号格式
        boolean isValidLandline = phone.matches("^0\\d{2,3}-?\\d{7,8}$"); // 座机号格式
        
        if (!isValidMobile && !isValidLandline) {
            throw new RuntimeException("店铺电话格式不正确");
        }
        
        // 验证描述长度（可选字段）
        if (merchantInfo.getDescription() != null && merchantInfo.getDescription().length() > 200) {
            throw new RuntimeException("店铺简介最多200个字符");
        }
    }
}
